import pygame
import math
import random

# 初始化pygame
pygame.init()

# 屏幕大小
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("旋转六边形内弹跳的球")

# 颜色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)

# 物理参数
gravity = 0.1
friction = 0.99
elasticity = 0.8

# 六边形参数
num_sides = 6
radius = 250
center = (WIDTH // 2, HEIGHT // 2)
angle = 0
rotation_speed = 0.01

# 球参数
ball_radius = 20
ball_pos = [WIDTH // 2, HEIGHT // 2 - 200]
ball_vel = [random.uniform(-5, 5), 0]

def rotate_point(point, center, angle):
    """旋转点"""
    x, y = point
    cx, cy = center
    dx = x - cx
    dy = y - cy
    new_x = dx * math.cos(angle) - dy * math.sin(angle) + cx
    new_y = dx * math.sin(angle) + dy * math.cos(angle) + cy
    return (new_x, new_y)

def get_hexagon_points(center, radius, angle):
    """获取六边形的顶点"""
    points = []
    for i in range(num_sides):
        x = center[0] + radius * math.cos(2 * math.pi * i / num_sides + angle)
        y = center[1] + radius * math.sin(2 * math.pi * i / num_sides + angle)
        points.append((x, y))
    return points

def point_on_line(p1, p2, t):
    """获取线段上的点"""
    return (p1[0] + (p2[0] - p1[0]) * t, p1[1] + (p2[1] - p1[1]) * t)

def distance(p1, p2):
    """计算两点之间的距离"""
    return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)

def closest_point_on_segment(p, p1, p2):
    """获取点到线段的最短距离点"""
    dx = p2[0] - p1[0]
    dy = p2[1] - p1[1]
    t = ((p[0] - p1[0]) * dx + (p[1] - p1[1]) * dy) / (dx * dx + dy * dy)
    t = max(0, min(1, t))
    return point_on_line(p1, p2, t)

def check_collision(ball_pos, ball_radius, hexagon_points):
    """检查球是否与六边形的边碰撞"""
    for i in range(len(hexagon_points)):
        p1 = hexagon_points[i]
        p2 = hexagon_points[(i + 1) % len(hexagon_points)]
        closest = closest_point_on_segment(ball_pos, p1, p2)
        dist = distance(ball_pos, closest)
        if dist < ball_radius:
            return i, closest
    return None, None

def reflect_velocity(ball_vel, normal):
    """根据法线反射速度"""
    dot = ball_vel[0] * normal[0] + ball_vel[1] * normal[1]
    ball_vel[0] -= 2 * dot * normal[0]
    ball_vel[1] -= 2 * dot * normal[1]
    ball_vel[0] *= elasticity
    ball_vel[1] *= elasticity

# 主循环
running = True
clock = pygame.time.Clock()

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 更新六边形旋转角度
    angle += rotation_speed

    # 获取六边形的顶点
    hexagon_points = get_hexagon_points(center, radius, angle)

    # 更新球的位置和速度
    ball_vel[1] += gravity
    ball_pos[0] += ball_vel[0]
    ball_pos[1] += ball_vel[1]

    # 检查碰撞
    collision_index, collision_point = check_collision(ball_pos, ball_radius, hexagon_points)
    if collision_index is not None:
        # 计算法线
        p1 = hexagon_points[collision_index]
        p2 = hexagon_points[(collision_index + 1) % len(hexagon_points)]
        dx = p2[0] - p1[0]
        dy = p2[1] - p1[1]
        normal = (-dy, dx)
        length = math.sqrt(normal[0] ** 2 + normal[1] ** 2)
        normal = (normal[0] / length, normal[1] / length)

        # 反射速度
        reflect_velocity(ball_vel, normal)

        # 将球移出碰撞点
        ball_pos[0] = collision_point[0] + normal[0] * ball_radius
        ball_pos[1] = collision_point[1] + normal[1] * ball_radius

    # 应用摩擦力
    ball_vel[0] *= friction
    ball_vel[1] *= friction

    # 清屏
    screen.fill(WHITE)

    # 绘制六边形
    pygame.draw.polygon(screen, BLACK, hexagon_points, 2)

    # 绘制球
    pygame.draw.circle(screen, RED, (int(ball_pos[0]), int(ball_pos[1])), ball_radius)

    # 更新屏幕
    pygame.display.flip()

    # 控制帧率
    clock.tick(60)

pygame.quit()